using System;
using System.Collections;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Networking;

[RequireComponent(typeof(AudioSource))]
[RequireComponent(typeof(NetworkIdentity))]
public class DamageManager : NetworkBehaviour
{
	[Header("Living")]
	public bool IsAlive = true;

	[SyncVar(hook = "OnHPChanged")]
	public byte HP = 100;

	public byte HPmax = 100;

	public GameObject DeadReplacement;

	public float DeadReplaceLifeTime = 180f;

	public bool DestroyOnDead = true;

	public AudioClip[] SoundPain;

	public AudioSource Audiosource;

	[HideInInspector]
	public bool dieByLifeTime;

	[HideInInspector]
	public bool spectreThis;

	[HideInInspector]
	[SyncVar]
	public byte Team;

	[HideInInspector]
	[SyncVar]
	public int NetID = -1;

	[SyncVar]
	[HideInInspector]
	public string UserID = string.Empty;

	[SyncVar]
	[HideInInspector]
	public string UserName = string.Empty;

	[HideInInspector]
	[SyncVar]
	public int LastHitByID = -1;

	private Vector3 directionHit;

	private byte lastHP;

	private bool alreadyDead;

	private bool isQuitting;

	private static int kCmdCmdOnDead;

	private static int kRpcRpcODead;

	private static int kCmdCmdRespawn;

	private static int kRpcRpcRespawn;

	public byte NetworkHP
	{
		get
		{
			return HP;
		}
		[param: In]
		set
		{
			ref byte hP = ref HP;
			if (NetworkServer.localClientActive && !base.syncVarHookGuard)
			{
				base.syncVarHookGuard = true;
				OnHPChanged(value);
				base.syncVarHookGuard = false;
			}
			SetSyncVar(value, ref hP, 1u);
		}
	}

	public byte NetworkTeam
	{
		get
		{
			return Team;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref Team, 2u);
		}
	}

	public int NetworkNetID
	{
		get
		{
			return NetID;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref NetID, 4u);
		}
	}

	public string NetworkUserID
	{
		get
		{
			return UserID;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref UserID, 8u);
		}
	}

	public string NetworkUserName
	{
		get
		{
			return UserName;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref UserName, 16u);
		}
	}

	public int NetworkLastHitByID
	{
		get
		{
			return LastHitByID;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref LastHitByID, 32u);
		}
	}

	public virtual void Awake()
	{
	}

	public virtual void Start()
	{
		Audiosource = GetComponent<AudioSource>();
	}

	public override void OnStartClient()
	{
		if (HP <= 0)
		{
			SetEnable(enable: false);
		}
		base.OnStartClient();
	}

	public virtual void Update()
	{
		if (HP > HPmax)
		{
			NetworkHP = HPmax;
		}
	}

	public virtual void DirectDamage(DamagePackage pack)
	{
		ApplyDamage((byte)(float)(int)pack.Damage, pack.Direction, pack.ID, pack.Team);
	}

	public virtual void ApplyDamage(byte damage, Vector3 direction, int attackerID, byte team)
	{
		directionHit = direction;
		DoApplyDamage(damage, direction, attackerID, team);
		if ((bool)Audiosource && SoundPain.Length > 0)
		{
			Audiosource.PlayOneShot(SoundPain[UnityEngine.Random.Range(0, SoundPain.Length)]);
		}
	}

	public virtual void DoApplyDamage(byte damage, Vector3 direction, int attackerID, byte team)
	{
		if (!base.isServer)
		{
			return;
		}
		lastHP = HP;
		directionHit = direction;
		if ((Team == team && team != 0) || HP <= 0)
		{
			return;
		}
		if (damage >= HP)
		{
			NetworkHP = 0;
			NetworkLastHitByID = attackerID;
			CallCmdOnDead(LastHitByID, NetID, "Kill");
			return;
		}
		NetworkHP = (byte)(HP - damage);
		if (HP <= 0)
		{
			NetworkLastHitByID = attackerID;
			CallCmdOnDead(LastHitByID, NetID, "Kill");
		}
	}

	private void OnHPChanged(byte hp)
	{
		if (hp <= 0)
		{
			SetEnable(enable: false);
		}
		else if (hp >= HPmax && !IsAlive)
		{
			SetEnable(enable: true);
		}
		if (!IsAlive && lastHP > 0 && !alreadyDead)
		{
			SpawnDeadBody();
			alreadyDead = true;
		}
		lastHP = HP;
		NetworkHP = hp;
	}

	private void SpawnDeadBody()
	{
		if (!isQuitting && (bool)DeadReplacement)
		{
			GameObject gameObject = UnityEngine.Object.Instantiate(DeadReplacement, base.transform.position, Quaternion.identity);
			OnDeadBodySpawned(gameObject);
			CopyTransformsRecurse(base.transform, gameObject);
			if (dieByLifeTime)
			{
				DeadReplaceLifeTime = 3f;
			}
			UnityEngine.Object.Destroy(gameObject, DeadReplaceLifeTime);
		}
	}

	[Command(channel = 0)]
	private void CmdOnDead(int killer, int me, string killtype)
	{
		CallRpcODead(killer, me, killtype);
	}

	[ClientRpc(channel = 0)]
	private void RpcODead(int killer, int me, string killtype)
	{
		OnThisThingDead();
		OnKilled(killer, me, killtype);
		if (DestroyOnDead)
		{
			UnityEngine.Object.Destroy(base.gameObject, 5f);
		}
	}

	public void ReSpawn(byte team, int spawner)
	{
		CallCmdRespawn(team, spawner);
	}

	public void ReSpawn(int spawner)
	{
		CallCmdRespawn(Team, spawner);
	}

	[Command(channel = 0)]
	private void CmdRespawn(byte team, int spawner)
	{
		NetworkHP = HPmax;
		NetworkTeam = team;
		CallRpcRespawn(team, spawner);
	}

	[ClientRpc(channel = 0)]
	private void RpcRespawn(byte team, int spawner)
	{
		NetworkHP = HPmax;
		NetworkTeam = team;
		OnRespawn(spawner);
	}

	public virtual void SetEnable(bool enable)
	{
		IsAlive = enable;
		IEnumerator enumerator = base.transform.GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				Transform transform = (Transform)enumerator.Current;
				transform.gameObject.SetActive(enable);
			}
		}
		finally
		{
			IDisposable disposable;
			if ((disposable = (enumerator as IDisposable)) != null)
			{
				disposable.Dispose();
			}
		}
		Renderer[] componentsInChildren = GetComponentsInChildren<Renderer>();
		Renderer[] array = componentsInChildren;
		foreach (Renderer renderer in array)
		{
			renderer.enabled = enable;
		}
	}

	public virtual void OnKilled(int killer, int me, string killtype)
	{
	}

	public virtual void OnThisThingDead()
	{
	}

	public virtual void OnRespawn(int spawner)
	{
		alreadyDead = false;
	}

	public virtual void OnDestroyed()
	{
	}

	public virtual void OnDeadBodySpawned(GameObject deadbody)
	{
	}

	public void CopyTransformsRecurse(Transform src, GameObject dst)
	{
		dst.transform.position = src.position;
		dst.transform.rotation = src.rotation;
		if ((bool)dst.GetComponent<Rigidbody>())
		{
			dst.GetComponent<Rigidbody>().AddForce(directionHit * 5f, ForceMode.VelocityChange);
		}
		IEnumerator enumerator = dst.transform.GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				Transform transform = (Transform)enumerator.Current;
				Transform transform2 = src.Find(transform.name);
				if ((bool)transform2)
				{
					CopyTransformsRecurse(transform2, transform.gameObject);
				}
			}
		}
		finally
		{
			IDisposable disposable;
			if ((disposable = (enumerator as IDisposable)) != null)
			{
				disposable.Dispose();
			}
		}
	}

	private void OnApplicationQuit()
	{
		isQuitting = true;
	}

	public override void OnNetworkDestroy()
	{
		if (!isQuitting)
		{
			OnDestroyed();
			base.OnNetworkDestroy();
		}
	}

	private void UNetVersion()
	{
	}

	protected static void InvokeCmdCmdOnDead(NetworkBehaviour obj, NetworkReader reader)
	{
		if (!NetworkServer.active)
		{
			UnityEngine.Debug.LogError("Command CmdOnDead called on client.");
		}
		else
		{
			((DamageManager)obj).CmdOnDead((int)reader.ReadPackedUInt32(), (int)reader.ReadPackedUInt32(), reader.ReadString());
		}
	}

	protected static void InvokeCmdCmdRespawn(NetworkBehaviour obj, NetworkReader reader)
	{
		if (!NetworkServer.active)
		{
			UnityEngine.Debug.LogError("Command CmdRespawn called on client.");
		}
		else
		{
			((DamageManager)obj).CmdRespawn((byte)reader.ReadPackedUInt32(), (int)reader.ReadPackedUInt32());
		}
	}

	public void CallCmdOnDead(int killer, int me, string killtype)
	{
		if (!NetworkClient.active)
		{
			UnityEngine.Debug.LogError("Command function CmdOnDead called on server.");
			return;
		}
		if (base.isServer)
		{
			CmdOnDead(killer, me, killtype);
			return;
		}
		NetworkWriter networkWriter = new NetworkWriter();
		networkWriter.Write((short)0);
		networkWriter.Write((short)5);
		networkWriter.WritePackedUInt32((uint)kCmdCmdOnDead);
		networkWriter.Write(GetComponent<NetworkIdentity>().netId);
		networkWriter.WritePackedUInt32((uint)killer);
		networkWriter.WritePackedUInt32((uint)me);
		networkWriter.Write(killtype);
		SendCommandInternal(networkWriter, 0, "CmdOnDead");
	}

	public void CallCmdRespawn(byte team, int spawner)
	{
		if (!NetworkClient.active)
		{
			UnityEngine.Debug.LogError("Command function CmdRespawn called on server.");
			return;
		}
		if (base.isServer)
		{
			CmdRespawn(team, spawner);
			return;
		}
		NetworkWriter networkWriter = new NetworkWriter();
		networkWriter.Write((short)0);
		networkWriter.Write((short)5);
		networkWriter.WritePackedUInt32((uint)kCmdCmdRespawn);
		networkWriter.Write(GetComponent<NetworkIdentity>().netId);
		networkWriter.WritePackedUInt32(team);
		networkWriter.WritePackedUInt32((uint)spawner);
		SendCommandInternal(networkWriter, 0, "CmdRespawn");
	}

	protected static void InvokeRpcRpcODead(NetworkBehaviour obj, NetworkReader reader)
	{
		if (!NetworkClient.active)
		{
			UnityEngine.Debug.LogError("RPC RpcODead called on server.");
		}
		else
		{
			((DamageManager)obj).RpcODead((int)reader.ReadPackedUInt32(), (int)reader.ReadPackedUInt32(), reader.ReadString());
		}
	}

	protected static void InvokeRpcRpcRespawn(NetworkBehaviour obj, NetworkReader reader)
	{
		if (!NetworkClient.active)
		{
			UnityEngine.Debug.LogError("RPC RpcRespawn called on server.");
		}
		else
		{
			((DamageManager)obj).RpcRespawn((byte)reader.ReadPackedUInt32(), (int)reader.ReadPackedUInt32());
		}
	}

	public void CallRpcODead(int killer, int me, string killtype)
	{
		if (!NetworkServer.active)
		{
			UnityEngine.Debug.LogError("RPC Function RpcODead called on client.");
			return;
		}
		NetworkWriter networkWriter = new NetworkWriter();
		networkWriter.Write((short)0);
		networkWriter.Write((short)2);
		networkWriter.WritePackedUInt32((uint)kRpcRpcODead);
		networkWriter.Write(GetComponent<NetworkIdentity>().netId);
		networkWriter.WritePackedUInt32((uint)killer);
		networkWriter.WritePackedUInt32((uint)me);
		networkWriter.Write(killtype);
		SendRPCInternal(networkWriter, 0, "RpcODead");
	}

	public void CallRpcRespawn(byte team, int spawner)
	{
		if (!NetworkServer.active)
		{
			UnityEngine.Debug.LogError("RPC Function RpcRespawn called on client.");
			return;
		}
		NetworkWriter networkWriter = new NetworkWriter();
		networkWriter.Write((short)0);
		networkWriter.Write((short)2);
		networkWriter.WritePackedUInt32((uint)kRpcRpcRespawn);
		networkWriter.Write(GetComponent<NetworkIdentity>().netId);
		networkWriter.WritePackedUInt32(team);
		networkWriter.WritePackedUInt32((uint)spawner);
		SendRPCInternal(networkWriter, 0, "RpcRespawn");
	}

	static DamageManager()
	{
		kCmdCmdOnDead = 520619233;
		NetworkBehaviour.RegisterCommandDelegate(typeof(DamageManager), kCmdCmdOnDead, InvokeCmdCmdOnDead);
		kCmdCmdRespawn = 1407909610;
		NetworkBehaviour.RegisterCommandDelegate(typeof(DamageManager), kCmdCmdRespawn, InvokeCmdCmdRespawn);
		kRpcRpcODead = 1287728543;
		NetworkBehaviour.RegisterRpcDelegate(typeof(DamageManager), kRpcRpcODead, InvokeRpcRpcODead);
		kRpcRpcRespawn = -117768620;
		NetworkBehaviour.RegisterRpcDelegate(typeof(DamageManager), kRpcRpcRespawn, InvokeRpcRpcRespawn);
		NetworkCRC.RegisterBehaviour("DamageManager", 0);
	}

	public override bool OnSerialize(NetworkWriter writer, bool forceAll)
	{
		if (forceAll)
		{
			writer.WritePackedUInt32(HP);
			writer.WritePackedUInt32(Team);
			writer.WritePackedUInt32((uint)NetID);
			writer.Write(UserID);
			writer.Write(UserName);
			writer.WritePackedUInt32((uint)LastHitByID);
			return true;
		}
		bool flag = false;
		if ((base.syncVarDirtyBits & 1) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.WritePackedUInt32(HP);
		}
		if ((base.syncVarDirtyBits & 2) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.WritePackedUInt32(Team);
		}
		if ((base.syncVarDirtyBits & 4) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.WritePackedUInt32((uint)NetID);
		}
		if ((base.syncVarDirtyBits & 8) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.Write(UserID);
		}
		if ((base.syncVarDirtyBits & 0x10) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.Write(UserName);
		}
		if ((base.syncVarDirtyBits & 0x20) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.WritePackedUInt32((uint)LastHitByID);
		}
		if (!flag)
		{
			writer.WritePackedUInt32(base.syncVarDirtyBits);
		}
		return flag;
	}

	public override void OnDeserialize(NetworkReader reader, bool initialState)
	{
		if (initialState)
		{
			HP = (byte)reader.ReadPackedUInt32();
			Team = (byte)reader.ReadPackedUInt32();
			NetID = (int)reader.ReadPackedUInt32();
			UserID = reader.ReadString();
			UserName = reader.ReadString();
			LastHitByID = (int)reader.ReadPackedUInt32();
			return;
		}
		int num = (int)reader.ReadPackedUInt32();
		if ((num & 1) != 0)
		{
			OnHPChanged((byte)reader.ReadPackedUInt32());
		}
		if ((num & 2) != 0)
		{
			Team = (byte)reader.ReadPackedUInt32();
		}
		if ((num & 4) != 0)
		{
			NetID = (int)reader.ReadPackedUInt32();
		}
		if ((num & 8) != 0)
		{
			UserID = reader.ReadString();
		}
		if ((num & 0x10) != 0)
		{
			UserName = reader.ReadString();
		}
		if ((num & 0x20) != 0)
		{
			LastHitByID = (int)reader.ReadPackedUInt32();
		}
	}
}
